package org.finesys.tika.service;

import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.parser.AutoDetectParser;
import org.apache.tika.sax.BodyContentHandler;
import org.finesys.common.core.exception.BusinessException;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.xml.sax.SAXException;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.io.*;

/**
 * 文档解析服务
 */
@Service
public class DocumentParserService {
    /**
     * 解析文件内容，并返回解析后的字符串。
     *
     * @param file 要解析的文件
     * @return 解析后的字符串
     */
    public String parseDocument(File file) {
        StringBuilder sb = new StringBuilder();
        try (FileInputStream inputStream = new FileInputStream(file)) {
            // 这里可以调用Tika或者其他库来解析文件内容,解除限制
            BodyContentHandler handler = new BodyContentHandler(-1);
            Metadata metadata = new Metadata();
            AutoDetectParser parser = new AutoDetectParser();
            parser.parse(inputStream, handler, metadata);
            // 例如：
            sb.append(handler.toString());
        } catch (IOException | SAXException | TikaException e) {
            throw new RuntimeException(e);
        }
        return sb.toString();
    }


    /**
     * 解析文件内容，并返回解析后的字符串。
     *
     * @param multipartFile 要解析的文件
     * @return 解析后的字符串
     */
    public String parseDocument(MultipartFile multipartFile) {
        // 将MultipartFile转换为File
        try {
            File file = File.createTempFile("document_", ".tmp");
            // 将MultipartFile的内容写入到文件
            multipartFile.transferTo(file);
            // 删除临时文件
            file.deleteOnExit();
            return parseDocument(file);
        } catch (IOException e) {
            throw new BusinessException("文件解析失败", e);
        }
    }


    /**
     * 解析内容并返回解析结果。
     *
     * @param content 待解析的内容
     * @return Mono<String> 返回一个包含解析结果的Mono对象
     * @throws Exception 解析过程中可能出现的异常
     */
    public Mono<String> parseContent(Flux<DataBuffer> content) {
        return DataBufferUtils.join(content).flatMap(dataBuffer -> {
            try {
                byte[] bytes = new byte[dataBuffer.readableByteCount()];
                dataBuffer.read(bytes);
                DataBufferUtils.release(dataBuffer);
                //
                BodyContentHandler handler = new BodyContentHandler(-1);
                Metadata metadata = new Metadata();
                AutoDetectParser parser = new AutoDetectParser();
                parser.parse(new ByteArrayInputStream(bytes), handler, metadata);
                return Mono.just(handler.toString());
            } catch (Exception e) {
                return Mono.error(e);
            }
        });
    }

    /**
     * 将InputStream解析为Mono<String>类型的数据
     *
     * @param inputStream 需要解析的InputStream对象
     * @return 返回解析后的Mono<String>对象
     * @throws RuntimeException 如果解析过程中出现异常，将抛出此异常
     */
    public Mono<String> parseToMono(InputStream inputStream) {
        return Mono.create(sink -> {
            try {
                BodyContentHandler handler = new BodyContentHandler(-1);
                Metadata metadata = new Metadata();
                AutoDetectParser parser = new AutoDetectParser();
                parser.parse(inputStream, handler, metadata);
                sink.success(handler.toString());
            } catch (Exception e) {
                sink.error(new RuntimeException("解析失败", e));
            } finally {
                if (inputStream != null) {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                    }
                }
            }
        });
    }
}
